package cn.learn.jdk8new.lambda;

import org.junit.Test;

import java.util.Comparator;
import java.util.TreeSet;
import java.util.function.Consumer;
import java.util.stream.IntStream;

/**
 * 学习lambda表达式的  基础语法
 *
 * @author huangyezhan
 * @version 1.0
 * @date 2020年03月23日20:03
 */
public class LearnLambda1 {

    /*
     * 对于耗时的操作用lambda表达式的for循环，如数据库的IO操作，多线程充分利用CPU资源（多线程处理）；
     * 对于不太耗时的操作使用普通for循环，比如纯CPU计算类型的操作，单线程性能更高，减少上下文切换的开销。
     */
    @Test
    public void test1() {
        int  a[]    = {1, 22, 33, -12, -16, -22, -13};
        long start1 = System.currentTimeMillis();
        int  min    = Integer.MAX_VALUE;
        for (int i : a) {
            if (i < min) {
                min = i;
            }
        }
        long end = System.currentTimeMillis() - start1;
        System.out.println("结果：" + min + "  耗时：" + end);


        long start2 = System.currentTimeMillis();
        int  asInt  = IntStream.of(a).min().getAsInt();
        long end2   = System.currentTimeMillis() - start2;
        System.out.println("结果：" + asInt + "  耗时：" + end2);
    }

    /**
     * lambda做写 匿名内部类
     */
    @Test
    public void test2() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("ok");
            }
        }).start();

        //jdk8 lambda表达式
        new Thread(() -> System.out.println("ok")).start();


        //例子：
        Comparator<Integer> comparator1 = new Comparator<Integer>() {
            public int compare(Integer o1, Integer o2) {
                return Integer.compare(o1, o2);
            }
        };
        TreeSet<Integer> ts1 = new TreeSet<>(comparator1);

        //lambda写法1
        Comparator<Integer> comparator2 = (x, y) -> Integer.compare(x, y);
        TreeSet<Integer>    ts2         = new TreeSet<>(comparator2);
        //lambda写法2
        Comparator<Integer> comparator3 = Integer::compare;
        TreeSet<Integer>    ts3         = new TreeSet<>(comparator3);
    }

    /*
     * 一、Lambda表达式的基础语法：java8中引入了一个新的操作符”->“该操作符称为箭头操作符或Lambda操作符
     * Lambda操作符拆分成两部分：
     *      左侧：Lambda 表达式的参数列表
     *      右侧：Lambda 表达式中所需执行的功能，即Lambda 体
     * 语法格式一：无参数，无返回值
     *      ()->  System.out.println("Hello Lambda");
     *
     * 语法格式二：有参数，无返回值
     *      (x) -> System.out.println(x);
     *
     * 语法格式三：只有一个参数，左侧小括号可以不写
     *      x -> System.out.println(x);
     *
     * 语法格式四：有两个以上的参数，有返回值，并且Lambda 体中有多条语句
            Comparator<Integer> com = (x, y) -> {
                System.out.println("--");
                return Integer.compare(x, y);
            };
     *
     * 语法格式五：Lambda体中只有一条语句，return 和 大括号都可以不写
     *      Comparator<Integer> com2 = (x, y) -> Integer.compare(x, y);
     *
     * 语法格式六：Lambda体中的参数列表的类型可以省略不写（JVM编译器可以通过上下文识别出数据类型），如果有一个写了数据类型，就全部都写
     *      Comparator<Integer> com2 = (Integer x, Integer y) -> Integer.compare(x, y);
     *
     * 二、Lambda 表达式需要”函数式接口“的支持
     *  函数式接口：接口中只有一个抽象方法的接口，称为函数式接口。可以使用 @FunctionalInterface 修饰；可以检查是否是函数式接口。
     */

    /**
     * lambda 匿名内部类的多种写法；Lambda表达式相当于获取了一个实例
     */
    @Test
    public void test3() {
        /*
         * java1.7以前，匿名内部类用到外面的参数，外面的参数必须要用final 修饰；如下应该定义为：final int j = 3;
         * Java8后，不用了，不过在匿名内部类里面引用依然不能修改里面的参数值，相当于默认加上了
         */
        int j = 3;
        //匿名内部类
        LambdaDemo1 demo = new LambdaDemo1() {
            @Override
            public int setNum(int i) {
                System.out.println(j);
                return i + 2;
            }
        };
        int num = demo.setNum(3);
        System.out.println(num);

        //lambda写法1（最常用的写法）
        LambdaDemo1 demo1 = i -> i * 2;
        int         num1  = demo1.setNum(5);
        System.out.println(num1);

        //lambda写法2
        LambdaDemo1 demo2 = (i) -> i * 2;
        //lambda写法3
        LambdaDemo1 demo3 = (int i) -> i * 2;
        //lambda写法4
        LambdaDemo1 demo4 = (int i) -> {
            System.out.println("多行代码的写法" + j);
            return i * 2;
        };
    }


    @Test
    public void test4() {
        /**
         * 语法格式二：Lambda有参数列表，无返回值
         */
        Consumer<String> con = (x) -> System.out.println(x);
        con.accept("Lambda有参数列表，无返回值");

        /**
         * 语法格式四：Lambda有参数列表，无返回值
         */
        Comparator<Integer> com1 = (x, y) -> {
            System.out.println("--");
            return Integer.compare(x, y);
        };
        /**
         * 语法格式五：Lambda体中只有一条语句，return 和 大括号都可以不写
         */
        Comparator<Integer> com2 = (x, y) -> Integer.compare(x, y);
    }

    @Test
    public void test5(){
        Integer     num = opertionNum(5, i -> i + 2);
        System.out.println(num);

    }

    public Integer opertionNum(Integer i, LambdaDemo1 d){
        return d.setNum(i);
    }


}
